home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
039a
/
d3d.zip
/
SPH80.C
< prev
next >
Wrap
Text File
|
1989-11-22
|
4KB
|
160 lines
/* SPH80: Polyhedron with 80 triangular faces to approximate a sphere.
It is based on an icosahedron, which is a regular polyhedron with
20 equilateral triangles, four smaller traingles are used, which gives
20 x 4 = 90 of these smaller triangles (not equilateral). For each
equilateral triangle of the icosahedron, the midpoints of its three
sides are projected onto the sphere in which the icosahedron fits.
We obtain the four smaller triangles by connecting the neighboring
points. */
#include <stdio.h>
#include <math.h>
#include <process.h>
void point(int i, float x, float y, float z);
void subdivide(int A, int B, int C);
void storeface(int i, int j, int k);
void midpnt(int B, int C, int *pP, float x, float y, float z);
int npoints;
struct {float x, y, z;} pnt[43];
int nface=0;
struct {int i, j, k;} fc[80];
int nedge=0;
struct {i, j, P;} edges[120];
FILE *fp;
main()
{
int i, l;
double pi, r, alpha, tau;
pi = 4.0 * atan(1.0);
tau = (sqrt(5.0) + 1)/2; /* tau = 2 * cos(pi/5.0) */
r = tau - 0.5;
printf("A sphere (with radius 1) is approximated\n");
printf("by an object with 80 triangular bounding\n");
printf("faces. The results are written to the \n");
printf("object file SPH80.DAT (which is read by D3D.\n");
fp = fopen("SPH80.DAT","w");
point(1, 0.0, 0.0, 1.0); /* North Pole */
for(i=0; i<5; i++) {
alpha = -pi/5 + i*pi/2.5; /* degrees: -36 + i*72 */
point(2+i, cos(alpha)/r, sin(alpha)/r, 0.5/r);
}
for(i=0; i<5; i++) {
alpha = i * pi/2.5;
point(7+i, cos(alpha)/r, sin(alpha)/r, -0.5/r);
}
point(12, 0.0, 0.0, -1.0); /* South Pole */
npoints = 12;
for(i=0; i<5; i++) subdivide(1, 2+i, i<4 ? 3+i : 2);
for(i=0; i<5; i++) subdivide(2+i, 7+i, i<4 ? 3+i : 2);
for(i=0; i<5; i++) subdivide(7+i, i<4 ? 8+i : 7, i<4 ? 3+i : 2);
for(i=0; i<5; i++) subdivide(7+i, 12, i<4 ? 8+i : 7);
fprintf(fp, "Faces:\n");
for(l=0; l<80; l++)
fprintf(fp, "%d %d %d.\n", fc[l].i, fc[l].j, fc[l].k);
fclose(fp);
}
void midpnt(int B, int C, int *pP, float x, float y, float z)
/* Point(x, y, z) is the midpoint of BC. If it is a new vertex,
store it and write it to the object file, using a new vertex
number. If not, find its vertex number. The vertex number
is to be assigned to *pP anyway.
*/
{
int tmp, e;
if(C < B) {
tmp = B;
B = C;
C = tmp;
}
/* B, C in increasing order, for the sake of uniqueness */
for(e=0; e<nedge; e++)
if(edges[e].i == B && edges[e].j == C)
break;
if(e == nedge) { /* Not found, so we have a new vertex */
edges[e].i = B;
edges[e].j = C;
edges[e].P = *pP = ++npoints;
nedge++;
point(*pP, x, y, z);
}
else
*pP = edges[e].P;
/* Edge BD has been dealt with before,
so the vertex is not new. */
}
void point(int i, float x, float y, float z)
{
fprintf(fp, "%d %f %f %f\n", i, x, y, z);
pnt[i].x = x;
pnt[i].y = y;
pnt[i].z = z;
}
void subdivide(int A, int B, int C)
/* Divide triangle ABC into four samller triangles */
{
float xP, xQ, xR,
yP, yQ, yR,
zP, zQ, zR;
int P, Q, R;
static float d = -1;
/* d is equal to -1 only before the first call of this function;
after this, d will have its correct value (between 0 and 1),
namely the distance between any midpoint and the center of the
sphere. We project all midpoints onto the sphere (with radius
1) by dividing their coordinates by d.
*/
xP = (pnt[B].x + pnt[C].x)/2;
yP = (pnt[B].y + pnt[C].y)/2;
zP = (pnt[B].z + pnt[C].z)/2;
xQ = (pnt[C].x + pnt[A].x)/2;
yQ = (pnt[C].y + pnt[A].y)/2;
zQ = (pnt[C].z + pnt[A].z)/2;
xR = (pnt[A].x + pnt[B].x)/2;
yR = (pnt[A].y + pnt[B].y)/2;
zR = (pnt[A].z + pnt[B].z)/2;
if (d < 0)
d = sqrt(xP*xP + yP*yP + zP*zP); /* 0 < d < 1 */
xP /= d; xQ /= d; xR /= d;
yP /= d; yQ /= d; yR /= d;
zP /= d; zQ /= d; zR /= d;
midpnt(B, C, &P, xP, yP, zP);
midpnt(C, A, &Q, xQ, yQ, zQ);
midpnt(A, B, &R, xR, yR, zR);
storeface(A, R, Q);
storeface(R, B, P);
storeface(Q, P, C);
storeface(Q, R, P);
}
void storeface(int i, int j, int k)
{
fc[nface].i = i;
fc[nface].j = j;
fc[nface].k = k;
nface++;
}